﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace TestServerApp2
{
    class Program
    {
        static int ClientCnt = 10;

        class Server
        {
            static byte[] GetBytes(string str)
            {
                byte[] bytes = new byte[str.Length * sizeof(char)];
                System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
                return bytes;
            }

            Socket s;
            IPEndPoint Addr;

            class myClient
            {
                public bool isAlive;
                public int clientNumber;
                public Socket mySocket;
                public Thread myThread;

                public myClient(int clNum)
                {
                    this.isAlive = true;
                    this.clientNumber = clNum;
                    this.myThread = new Thread(this.listenThread);
                }

                public void listenThread()
                {
                    while (isAlive)
                    {
                        try
                        {
                            byte[] msg = new byte[this.mySocket.Available];
                            this.mySocket.Receive(msg); //Принимаем МСГ
                            string message = Encoding.UTF8.GetString(msg);
                            message = message.Replace("\0\0", " ").Replace("\0", "");
                            if (message != "")
                            {
                                Console.WriteLine(clientNumber.ToString() + ": " + message); //Конвертируем и выводим
                            }
                        }
                        catch (Exception ex)
                        {
                            this.isAlive = false;
                            Console.WriteLine("client " + clientNumber.ToString() + " is Dead X_x. and said: " + ex.Message);
                        }
                    }
                }
            }
            myClient[] clients;
            int clientCnt;

            bool isRun;
            public Server()
            {
                this.s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                this.Addr = null;
                this.Addr = new IPEndPoint(IPAddress.Any, 8383); //"localhost" = 127.0.0.1
                this.s.Bind(Addr); //"Адресуем" сокет
                this.s.Listen(ClientCnt); //Обозначаем количество ожидающих в очереди на подключение

                this.clients = new myClient[ClientCnt];
                this.clientCnt = 0;
            }

            public void startServer()
            {
                Console.WriteLine("SERVER: startListen");
                this.isRun = true;
                // this.cl_s = this.s.Accept(); //Ожидаем подключения
                while (this.isRun)
                {
                    this.clients[this.clientCnt] = new myClient(this.clientCnt);

                    this.clients[this.clientCnt].mySocket = this.s.Accept();
                    this.clients[this.clientCnt].myThread.Start();
                    Console.WriteLine("Client {0} conected.", this.clientCnt);
                    this.clientCnt++;
                }
                for (int i = 0; i <= this.clientCnt; ++i)
                {
                    this.clients[i].isAlive = false;
                    Console.WriteLine("Client {0} stoped.", i);
                }
            }

            public void stopServer()
            {
                this.isRun = false;
            }

            public void sayToAll(string msg)
            {
                foreach (myClient cln in clients)
                {
                    if (cln.mySocket == null)
                        break;
                    byte[] bmsg = GetBytes(msg); //Конвертируем
                    cln.mySocket.Send(bmsg); //Отправляем
                }
            }
        }

        static void Main(string[] args)
        {
            bool go = true;
            Server servak = new Server();
            Thread oThread = new Thread(new ThreadStart(servak.startServer));

            String comand = "";
            while(go)
            {
                Console.Write("Input command:  ");
                comand = Console.ReadLine();
                switch (comand)
                {
                    case "start":
                        if(!oThread.IsAlive)
                            oThread.Start();
                        break;
                    case "stop":
                        servak.stopServer();
                        go = false;
                        break;
                    case "saytoall":
                        servak.sayToAll("Hello world!");
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
